/**
 * Renderer类，负责将Scene中的图元渲染为DOM元素，支持完整渲染和增量渲染
 */

import { Scene, PrimitiveType, Primitive, Layer } from './scene';
import { AppContext } from './context';

// 添加一个简单的工具函数，用于在浏览器控制台打印日志
function log(...args: any[]) {
  if (typeof console !== 'undefined') {
    console.log('[Renderer]', ...args);
  }
}

/**
 * 渲染器选项
 */
export interface RendererOptions {
  document?: Document;
  appContext?: AppContext;
}

/**
 * 渲染器类
 */
export class Renderer {
  private document: Document;
  private appContext: AppContext | null = null;
  private sceneMap: Map<Scene, HTMLElement> = new Map();

  constructor(options: RendererOptions = {}) {
    this.document = options.document || (typeof document !== 'undefined' ? document : ({} as Document));
    this.appContext = options.appContext || null;

    // 如果提供了AppContext，设置渲染回调
    if (this.appContext) {
      // 这里可以设置渲染回调，用于处理由context.notify()触发的渲染
    }
  }

  /**
   * 将Scene渲染为DOM元素（完整渲染）
   */
  renderScene(scene: Scene): HTMLElement {
    log('renderScene: 开始渲染Scene')
    document.body.style.margin = '0';
    document.body.style.padding = '0';
    const container = this.document.createElement('div');
    container.className = 'gpui-scene-container';
    container.style.position = 'relative';
    //container.style.backgroundColor = 'red';
    container.style.width = '100vw';
    container.style.height = '100vh';

    // 按图层顺序渲染
    const layers = scene.getLayers();

    log('renderScene: 图层数量:', layers.length)
    layers.forEach(layer => {
      log('renderScene: 渲染图层:', layer.id, '图元数量:', layer.primitives.length)
      const layerElement = this.renderLayer(layer);
      if (layerElement) {
        layerElement.style.zIndex = layer.zIndex.toString();
        layerElement.style.opacity = layer.opacity.toString();
        container.appendChild(layerElement);
        log('renderScene: 图层元素已添加到容器')
      }
    });

    // 保存场景和容器的映射关系
    this.sceneMap.set(scene, container);

    log('renderScene: Scene渲染完成')
    return container;
  }

  /**
   * 设置AppContext
   */
  setAppContext(appContext: AppContext): void {
    this.appContext = appContext;
  }

  /**
   * 注册场景到渲染器
   */
  registerScene(scene: Scene, container: HTMLElement): void {
    this.sceneMap.set(scene, container);
  }

  /**
   * 处理由context.notify()触发的场景更新
   * 这是增量渲染的关键入口
   */
  handleContextNotification(scene: Scene): void {
    const container = this.sceneMap.get(scene);
    if (container) {
      this.updateScene(scene, container);
    }
  }
  
  /**
   * 更新现有Scene的DOM表示（增量渲染）
   */
  updateScene(scene: Scene, existingContainer: HTMLElement): boolean {
    log('updateScene: 开始更新Scene')
    
    // 检查是否有任何更新
    if (!scene.hasUpdates()) {
      log('updateScene: 没有需要更新的内容')
      return false;
    }
    
    // 获取更新和删除的图元
    const updatedPrimitives = scene.getUpdatedPrimitives();
    const removedPrimitives = scene.getRemovedPrimitives();
    
    log('updateScene: 更新的图元数量:', updatedPrimitives.size)
    log('updateScene: 删除的图元数量:', removedPrimitives.size)
    
    // 处理删除的图元
    removedPrimitives.forEach(id => {
      const element = existingContainer.querySelector(`#${id}`);
      if (element && element.parentNode) {
        log('updateScene: 移除图元元素:', id)
        element.parentNode.removeChild(element);
      }
    });
    
    // 处理更新的图元
    scene.getLayers().forEach(layer => {
      // 找到对应图层的DOM元素
      const layerElement = existingContainer.querySelector(`.gpui-layer-${layer.id}`);
      if (!layerElement) {
        // 如果图层不存在，则创建并添加
        const newLayerElement = this.renderLayer(layer);
        if (newLayerElement) {
          newLayerElement.style.zIndex = layer.zIndex.toString();
          newLayerElement.style.opacity = layer.opacity.toString();
          existingContainer.appendChild(newLayerElement);
        }
        return;
      }
      
      // 处理图层中的更新图元
      layer.primitives.forEach(primitive => {
        if (updatedPrimitives.has(primitive.id)) {
          const existingElement = existingContainer.querySelector(`#${primitive.id}`);
          
          if (existingElement) {
            // 更新现有元素
            log('updateScene: 更新图元元素:', primitive.id)
            this.updatePrimitiveElement(primitive, existingElement as HTMLElement);
          } else {
            // 添加新元素
            log('updateScene: 添加新图元元素:', primitive.id)
            const newElement = this.renderPrimitive(primitive);
            (layerElement as HTMLElement).appendChild(newElement);
          }
        }
      });
    });
    
    // 重置更新标记
    scene.resetUpdateMarkers();
    
    log('updateScene: Scene更新完成')
    return true;
  }
  
  /**
   * 更新现有的图元DOM元素
   */
  private updatePrimitiveElement(primitive: Primitive, element: HTMLElement): void {
    // 更新位置和大小
    if (primitive.bounds) {
      element.style.left = `${primitive.bounds.x}px`;
      element.style.top = `${primitive.bounds.y}px`;
      element.style.width = `${primitive.bounds.width}px`;
      element.style.height = `${primitive.bounds.height}px`;
    }
    
    // 根据图元类型更新特定属性
    switch (primitive.type) {
      case PrimitiveType.RECT:
        this.updateRectElement(primitive, element);
        break;
      case PrimitiveType.TEXT:
        this.updateTextElement(primitive, element);
        break;
      case PrimitiveType.COMPONENT:
        this.updateComponentElement(primitive, element);
        break;
      case PrimitiveType.GROUP:
        this.updateGroupElement(primitive, element);
        break;
    }
  }
  
  /**
   * 更新矩形图元元素
   */
  private updateRectElement(primitive: Primitive, element: HTMLElement): void {
    // 更新样式属性
    if (primitive.properties) {
      Object.entries(primitive.properties).forEach(([key, value]) => {
        (element.style as any)[key] = value !== undefined ? value.toString() : '';
      });
    }
  }
  
  /**
   * 更新文本图元元素
   */
  private updateTextElement(primitive: Primitive, element: HTMLElement): void {
    if (primitive.properties && primitive.properties.text) {
      element.textContent = primitive.properties.text.toString();
    }
    
    // 更新样式属性
    if (primitive.properties) {
      const { text, ...styleProps } = primitive.properties;
      Object.entries(styleProps).forEach(([key, value]) => {
        (element.style as any)[key] = value !== undefined ? value.toString() : '';
      });
    }
  }
  
  /**
   * 更新组件图元元素
   */
  private updateComponentElement(primitive: Primitive, element: HTMLElement): void {
    if (primitive.properties && primitive.properties.componentId) {
      element.setAttribute('data-component-id', primitive.properties.componentId.toString());
    }
    
    // 更新样式属性
    if (primitive.properties) {
      const { componentId, props, componentInstance, ...styleProps } = primitive.properties;
      Object.entries(styleProps).forEach(([key, value]) => {
        (element.style as any)[key] = value !== undefined ? value.toString() : '';
      });
    }
    
    // 更新事件处理器
    if (primitive.properties && primitive.properties.componentInstance) {
      try {
        const componentInstance = primitive.properties.componentInstance;
        
        if (componentInstance && componentInstance.eventHandlers) {
          // 这里简化处理，实际项目中可能需要更复杂的事件解绑和重新绑定逻辑
          // 为了简单起见，我们只确保新的事件处理器被绑定
          if (componentInstance.eventHandlers instanceof Map) {
            componentInstance.eventHandlers.forEach((handlers: any[], eventType: string) => {
              handlers.forEach((handler: any) => {
                element.addEventListener(eventType as keyof HTMLElementEventMap, handler as EventListener);
              });
            });
          } else if (typeof componentInstance.eventHandlers === 'object') {
            Object.entries(componentInstance.eventHandlers).forEach(([eventType, handlers]) => {
              if (Array.isArray(handlers)) {
                handlers.forEach((handler: any) => {
                  element.addEventListener(eventType as keyof HTMLElementEventMap, handler as EventListener);
                });
              } else if (typeof handlers === 'function') {
                element.addEventListener(eventType as keyof HTMLElementEventMap, handlers as EventListener);
              }
            });
          }
        }
      } catch (error) {
        console.warn('[Renderer] 尝试更新组件事件处理器时出错:', error);
      }
    }
  }
  
  /**
   * 更新组图元元素
   */
  private updateGroupElement(primitive: Primitive, element: HTMLElement): void {
    // 更新样式属性
    if (primitive.properties) {
      Object.entries(primitive.properties).forEach(([key, value]) => {
        (element.style as any)[key] = value !== undefined ? value.toString() : '';
      });
    }
    
    // 这里简化处理，实际项目中可能需要更复杂的子元素更新逻辑
    if (primitive.children) {
      primitive.children.forEach(child => {
        const existingChildElement = element.querySelector(`#${child.id}`);
        if (existingChildElement) {
          // 如果子元素已存在，则更新它
          this.updatePrimitiveElement(child, existingChildElement as HTMLElement);
        } else {
          // 如果子元素不存在，则创建并添加它
          const childElement = this.renderPrimitive(child);
          element.appendChild(childElement);
        }
      });
    }
  }

  /**
   * 渲染图层
   */
  private renderLayer(layer: Layer): HTMLElement {
    const layerElement = this.document.createElement('div');
    layerElement.className = `gpui-layer gpui-layer-${layer.id}`;
    layerElement.style.position = 'absolute';
    layerElement.style.top = '0';
    layerElement.style.left = '0';
    layerElement.style.width = '100%';
    layerElement.style.height = '100%';
    
    // 渲染图层中的所有图元
    layer.primitives.forEach(primitive => {
      const domElement = this.renderPrimitive(primitive);
      if (domElement) {
        layerElement.appendChild(domElement);
      }
    });

    return layerElement;
  }

  /**
   * 渲染图元
   */
  private renderPrimitive(primitive: Primitive): HTMLElement {
    let element: HTMLElement;
    
    switch (primitive.type) {
      case PrimitiveType.RECT:
        element = this.renderRect(primitive);
        break;
      case PrimitiveType.TEXT:
        element = this.renderText(primitive);
        break;
      case PrimitiveType.COMPONENT:
        element = this.renderComponent(primitive);
        break;
      case PrimitiveType.GROUP:
        element = this.renderGroup(primitive);
        break;
      default:
        // 默认创建一个div元素
        element = this.document.createElement('div');
        break;
    }

    if (primitive.type && primitive.bounds) {
      element.style.position = 'absolute';
      element.style.left = `${primitive.bounds.x}px`;
      element.style.top = `${primitive.bounds.y}px`;
      element.style.width = `${primitive.bounds.width}px`;
      element.style.height = `${primitive.bounds.height}px`;
      element.id = primitive.id;
    }

    return element;
  }

  /**
   * 渲染矩形图元
   */
  private renderRect(primitive: Primitive): HTMLElement {
    const element = this.document.createElement('div');
    
    // 应用样式属性
    if (primitive.properties) {
      Object.entries(primitive.properties).forEach(([key, value]) => {
        if (value !== undefined) {
          (element.style as any)[key] = value.toString();
        }
      });
    }

    return element;
  }

  /**
   * 渲染文本图元
   */
  private renderText(primitive: Primitive): HTMLElement {
    const element = this.document.createElement('div');
    
    if (primitive.properties && primitive.properties.text) {
      element.textContent = primitive.properties.text.toString();
    }

    // 应用样式属性
    if (primitive.properties) {
      const { text, ...styleProps } = primitive.properties;
      Object.entries(styleProps).forEach(([key, value]) => {
        if (value !== undefined) {
          (element.style as any)[key] = value.toString();
        }
      });
    }

    return element;
  }

  /**
   * 渲染组件图元
   */
  private renderComponent(primitive: Primitive): HTMLElement {
    const element = this.document.createElement('div');
    
    if (primitive.properties && primitive.properties.componentId) {
      element.setAttribute('data-component-id', primitive.properties.componentId.toString());
    }

    // 应用样式属性
    if (primitive.properties) {
      const { componentId, props, ...styleProps } = primitive.properties;
      Object.entries(styleProps).forEach(([key, value]) => {
        if (value !== undefined) {
          (element.style as any)[key] = value.toString();
        }
      });
    }

    // 关键修复：为了支持事件处理，我们需要从图元中获取组件实例的事件处理器
    if (primitive.properties && primitive.properties.componentInstance) {
      try {
        const componentInstance = primitive.properties.componentInstance;
        
        // 如果组件实例有eventHandlers属性，直接绑定这些事件处理器
        if (componentInstance && componentInstance.eventHandlers) {
          // 检查eventHandlers的类型，确保我们正确处理
          if (componentInstance.eventHandlers instanceof Map) {
            // 如果是Map类型
            componentInstance.eventHandlers.forEach((handlers: any[], eventType: string) => {
              handlers.forEach((handler: any) => {
                // 使用类型断言确保TypeScript接受这些类型
                element.addEventListener(eventType as keyof HTMLElementEventMap, handler as EventListener);
              });
            });
          } else if (typeof componentInstance.eventHandlers === 'object') {
            // 如果是普通对象类型
            Object.entries(componentInstance.eventHandlers).forEach(([eventType, handlers]) => {
              if (Array.isArray(handlers)) {
                handlers.forEach((handler: any) => {
                  // 使用类型断言确保TypeScript接受这些类型
                  element.addEventListener(eventType as keyof HTMLElementEventMap, handler as EventListener);
                });
              } else if (typeof handlers === 'function') {
                // 使用类型断言确保TypeScript接受这些类型
                element.addEventListener(eventType as keyof HTMLElementEventMap, handlers as EventListener);
              }
            });
          }
        }
      } catch (error) {
        console.warn('[Renderer] 尝试绑定组件事件处理器时出错:', error);
      }
    }

    return element;
  }

  /**
   * 渲染组图元
   */
  private renderGroup(primitive: Primitive): HTMLElement {
    const element = this.document.createElement('div');
    element.style.position = 'relative';
    
    // 渲染子元素
    if (primitive.children) {
      primitive.children.forEach(child => {
        const childElement = this.renderPrimitive(child);
        element.appendChild(childElement);
      });
    }

    return element;
  }


}